<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }

      .root {
        width: 700px;
        min-height: 400px;
        margin: 50px auto;
        border: 1px solid #666;
        border-radius: 10px;
        padding: 10px;
      }

      #msgBox {
        display: flex;
        height: 400px;
        flex-direction: column;
        overflow-y: scroll;
        scrollbar-width: none; /* 隐藏标准滚动条（适用于现代浏览器）*/
        -ms-overflow-style: none; /* 隐藏IE和Edge浏览器的滚动条 */
      }

      /* 针对Webkit内核浏览器（例如Chrome和Safari），使用::-webkit-scrollbar伪元素隐藏滚动条 */
      #msgBox::-webkit-scrollbar {
        display: none;
      }

      #msgBox > div {
        padding: 10px;
        border: 1px solid #eee;
        margin-top: 10px;
        border-radius: 5px;
        display: inline-block;
      }

      .center {
        text-align: center;
      }

      .left {
        align-self: start;
        background-color: #fff;
      }

      .right {
        align-self: end;
        background-color: aquamarine;
      }

      .sender {
        display: flex;
        height: 30px;
      }

      .sender #ipMsg {
        flex: 1;
        padding: 0 10px;
      }

      .sender #fileInput {
        flex: 0.65;
        padding: 5px 0 0 0;
      }

      .sender button {
        width: 100px;
        margin-left: 5px;
      }

      .title {
        margin: 10px 0;
        background-color: #eee;
        padding: 10px;
      }

      hr {
        margin: 10px 0;
      }
    </style>
  </head>
  <body>
    <div class="root">
      <div class="sender">
        <input type="file" id="fileInput" />
        <input type="text" placeholder="please enter..." id="ipMsg" />
        <button id="btn">发送消息</button>
        <span
          style="
            font-size: 1.2rem;
            border: 1px solid #ccc;
            margin: 0 5px;
            border-radius: 5px;
          "
          class="emoji"
          id="spEmoji"
          >😖</span
        >
        <!-- <button id="btnClose">断开连接</button> -->
      </div>

      <h3 class="title center">消息列表</h3>
      <hr />

      <div id="msgBox"></div>
    </div>

    <!-- 老的IE浏览器不支持ws协议 安装socket.io兼容包即可 API略有不同 查查文档 -->
    <script>
      function isImageFile(filename) {
        return ["jpg", "jpeg", "png", "gif", "svg"].includes(
          filename.slice(filename.lastIndexOf(".") + 1)
        );
      }

      function getFileMsg(msg) {
        try {
          const data = JSON.parse(msg);
          console.log("data=", data);
          return data;
        } catch (err) {
          console.log("err=", err);
          return null;
        }
      }
    </script>

    <script>
      let cid;

      const onReceiveMsg = (msg) => {
        console.log("msg=", msg);

        // 接收文件
        if ((data = getFileMsg(msg))) {
          const { fileName, fileSize, from, to } = data.metaData;
          const fileData = new Uint8Array(data.fileData);
          const isImg = isImageFile(fileName);

          const fileBlob = new Blob([fileData], { type: "*/*" });
          const fileUrl = URL.createObjectURL(fileBlob);

          msg = `<a download=${fileName} href="${fileUrl}">下载文件</a>`;
          if (isImg) {
            msg += `<br/><img style="width:100px" src='${fileUrl}'/>`;
          }

          msgBox.innerHTML += `<div class="left">${msg}</div>`;
          return;
        }

        if (msg.startsWith("server: your cid is")) {
          document.title = cid = msg.slice(-3);
          return;
        }

        msgBox.innerHTML += `<div class="left">${msg}</div>`;
      };

      const onSendMsg = (msg) => {
        msgBox.innerHTML += `<div class="right">${msg}</div>`;
      };
    </script>

    <!-- 核心业务 -->
    <script>
      const msgs = [];

      // 发起远程连接请求websocket长连接
      var ws = new WebSocket("ws://localhost:8080");

      // 连接成功时打印一下
      ws.onopen = function () {
        console.log("ws onopen");

        // 向服务端的套接字发送消息 内容可字符 可字节 完全随意
        // ws.send('from client: hello');
      };

      // 收到服务端的消息
      ws.onmessage = function (e) {
        console.log("ws onmessage");

        // e.data 即服务端发来的消息数据
        console.log("server: " + e.data);
        onReceiveMsg(e.data);
      };

      ws.onerror = function (e) {
        //处理连接错误
        console.log("ws.onerror", e);
      };

      // 连接断开事件
      ws.onclose = function (e) {
        console.log("连接已断开");

        // 客户端主动断开连接
        // ws.close()
      };

      const sendMsg = () => {
        const msg = ipMsg.value;
        ws.send(msg);
        onSendMsg(msg);
        ipMsg.value = "";
      };
    </script>

    <!-- 各种用户交互事件 -->
    <script>
      // 点击按钮给服务端发送消息
      btn.onclick = function (e) {
        sendMsg();
      };

      // 点击按钮断开与服务端的连接
      btnClose.onclick = function (e) {
        ws.close();
        console.log("连接已断开");
      };

      document.onkeydown = (e) => {
        // console.log(e.key,e.keyCode);
        if (e.key === "Enter") {
          sendMsg();
        }
      };

      spEmoji.onclick = (e) => {
        ipMsg.value += e.target.innerText;
        sendMsg();
      };
    </script>

    <!-- 发送文件 -->
    <script>
      const fileInput = document.getElementById("fileInput");

      // 用户选定了文件
      fileInput.addEventListener("change", function (event) {
        // 获取用户选定的文件
        const file = event.target.files[0];

        // 创建文件读取器
        const reader = new FileReader();

        /* 文件数据读取完毕后触发FileReader的load事件 */
        reader.onload = function (event) {
          // 拿到文件数据
          const fileData = event.target.result;
          console.log("fileData", fileData);

          // 封装请求信息元数据
          const metaData = {
            fileName: file.name, //文件名
            fileSize: file.size, //文件的字节数
            from: cid, //文件的发送者是自己
            to: ipMsg.value, //从文本输入框拿取接受者的cid
          };

          const dataToSend = {
            metadata: metaData,
            fileData: Array.from(new Uint8Array(fileData)), // 将 ArrayBuffer 转换为数组
          };

          const jsonBody = JSON.stringify(dataToSend);
          console.log("jsonBody=", jsonBody);
          ws.send(jsonBody); // 发送封装后的数据
        };

        /* 读取文件数据 */
        // file要读取的文件 = 一缸水
        // buffer即一个缓冲区 = 一个瓢
        // 飘飘水形成的数组（ArrayBuffer） = 文件数据
        reader.readAsArrayBuffer(file);
      });
    </script>
    
  </body>
</html>
